import { Button, Input, message, Tabs, Table, Modal, Spin, Form, InputNumber, Space,Collapse,theme } from 'antd'
import { FolderOpenOutlined } from '@ant-design/icons';
import React,{ useContext, useEffect, useRef, useState } from 'react';
import { globalContext } from '../../components/context'
import md5 from 'md5'
import http from '../../lib/http'
import * as apis from '../../lib/api'
import Client3D from "../../lib/three";
import { cloneDeep } from 'lodash';
import Upload, {handleValue} from '../../components/upload'
import NormalTexture, { maps } from './normal_texture'
import { useLocation, useNavigate } from "react-router-dom";

const { Panel } = Collapse;

const Index = () => {
    const { token } = theme.useToken();
    const l = useLocation()
    const n = useNavigate()
    const [loading, setLoading] = useState(false)
    const [threeClient, setThreeClient] = useState(null)
    const [ak, setAk] = useState()
    const [tabs, setTabs] = useState([])
    const [stateMaterials, setStateMaterials] = useState({cutparts: []})
    const [meshs, setMeshs] = useState([])
    const [curCode, setCurCode] = useState()
    const canvasRef = useRef()
    const normalTextureRef = useRef()
    const {ossClient} = useContext(globalContext)
 

    useEffect(()=>{
        const params = new URLSearchParams(l.search)
        const id = params.get("id")
        setLoading(true)
        http.get(`${apis.PRODUCT_DETAIL}?id=${id}`).then(data => {
            if(!data.materials){
                setLoading(false)
                return
            }
            data.materials = JSON.parse(data.materials)
            console.log(data)
            setStateMaterials(data.materials)
            setTabs(data.materials.map_info)
           
            //启动3D场景
            let ops = {
                canvasDom: canvasRef?.current,
                canvasWidth: 375,
                canvasHeight: 667
            }
            //初始化3DClient
            let client = new Client3D(ops)
            setThreeClient(client)
  
            //启动3D场景
            client.start()
            client.loadModel(process.env.REACT_APP_OSS_URL+data.materials.obj_url, (p) => {
                console.log(p)
            }).then(r => {
                setMeshs(r?.getObjects()?.children)
                setLoading(false)
                if(data.materials.map_info && data.materials.map_info.length !== 0){
                    onTabsChange(data.materials.map_info[0].color, data.materials.map_info, client)
                }
            })            
        })
        
        return () => {
            threeClient?.destroy()
        }
    },[])

    //定价
    const confirmPrice = () => {
        if (stateMaterials.cutparts.find(i => i.code === curCode)){
            return
        }
        let f2 = meshs.find(i => i.name === curCode)
        let cpStateMaterials = cloneDeep(stateMaterials)
        cpStateMaterials.cutparts.push({
            code: curCode,
            txt: f2?.name,
            img: "",
            camera: null
        })
        console.log(cpStateMaterials)
        setStateMaterials(cpStateMaterials)
        message.success("操作成功，已添加到印刷部位列表")
    }

    //添加材质贴图
    const onEdit = async (e,action) => {
        if(action === "add"){
            const codes = []
            for(let i=0;i<meshs.length;i++){
                codes.push(meshs[i].name)
            }
            normalTextureRef.current.setCodes(codes)
            normalTextureRef.current.resetFields()
            normalTextureRef.current.setCurIndex([-1])
            normalTextureRef.current.setIsModalOpen(true)
        }
        if(action === "remove"){
            Modal.confirm({
                title: "提示",
                content: <p>确定删除吗?</p>,
                onOk: async () => {
                    const cpTabs = cloneDeep(tabs)
                    const index = cpTabs.findIndex(i => i.color === e)
                    cpTabs.splice(index,1)
                    setLoading(true)
                    if(cpTabs.length === 0){
                        for(let i=0;i<maps.length;i++){
                            threeClient.clearNormalMap(maps[i].value)
                        }
                    }else{
                        onTabsChange(cpTabs[0].color)
                    }
                    setLoading(false)
                    setTabs(cpTabs)
                }
            })
        }
    }

    //编辑材质贴图
    const editMap = () => {
        const index = tabs.findIndex(i => i.color === ak)
        const codes = []
        for(let i=0;i<meshs.length;i++){
            codes.push(meshs[i].name)
        }
        normalTextureRef.current.setCodes(codes)
        normalTextureRef.current.resetFields()
        normalTextureRef.current.setFieldsValue(tabs[index])
        normalTextureRef.current.setCurIndex([index])
        normalTextureRef.current.setIsModalOpen(true)
    }

    //编辑单个材质
    const editColorSingle = (v) => {
        let curTabIndex = tabs?.findIndex(i => i.color == ak)
        let curTab = tabs[curTabIndex]
        let colorInfoIndex = curTab?.codes_info?.findIndex(i => i.code == v.name)
        let colorInfo = curTab?.codes_info[colorInfoIndex]
        normalTextureRef.current.resetFields()
        normalTextureRef.current.setFieldsValue(colorInfo)
        normalTextureRef.current.setCurIndex([curTabIndex,colorInfoIndex])
        normalTextureRef.current.setIsModalOpen(true)
    }

    const TabLabel = ({name,color}) => {
        return (
            <div style={{display: "flex", alignContent:"center"}}>
                <span style={{width: 17, height: 17, background: color, display: "inline-block",marginRight: 3,marginTop: 3}}></span>
                <span>{name}</span>
            </div>
        )
    }

    //确认材质
    const normalTextureOnchange = async (val, cindex) => {
        console.log("valvalval",val)

        //主色的操作
        if(cindex.length == 1){
             //新增主色
            if(cindex[0] == -1){
                if(tabs?.find(i => i.color === val.color)){
                    message.error("已有相同颜色")
                    return false
                }
            }
            //更新主色
            if(cindex[0] != -1){
                if(tabs[[cindex[0]]].color === val.color){ //没有更新

                }else{
                    if(tabs?.find(i => i.color === val.color)){
                        message.error("已有相同颜色")
                        return false
                    }
                }
            }

            setLoading(true)
            try {
                for(let i=0;i<maps.length;i++){
                    threeClient.clearNormalMap(maps[i].value,val.color)
                }
               //加载所有贴图
               if(val?.codes_info && val?.codes_info.length !== 0){
                    for(let i=0;i<val.codes_info.length;i++){
                        let item = val.codes_info[i]
                        for(let j=0;j<item?.maps?.length;j++){
                            let jitem = item.maps[j]
                            await threeClient.setNormalMap(jitem.url,jitem.map,item.color,item.code)
                        }
                        
                    }
                }
                const cpTabs = cloneDeep(tabs || [])
                if(cindex[0] === -1){
                    cpTabs.push(val) 
                }else{
                    cpTabs[cindex[0]] = val
                }
                setTabs(cpTabs)
                setAk(val.color)
                setLoading(false)
                return true
            } catch (error) {
                console.log(error)
                message.error("加载失败")
            }
            setLoading(false)
            return true
        }

        //单个部位的更新
        setLoading(true)
        let curTab = tabs[cindex[0]]
        let curColorInfo = curTab?.codes_info[cindex[1]]


        if(val.color === curColorInfo.color){ //没有更新

        }else{
            if(curTab?.codes_info?.find(i => i.color === val.color)){
                message.error("已有相同颜色")
                return false
            }
        }
        const cpTabs = cloneDeep(tabs || [])
        cpTabs[cindex[0]].codes_info[cindex[1]] = {code: curCode, ...val}
        for(let i=0;i<maps.length;i++){
            threeClient.clearNormalMap(maps[i].value,val.color)
        }
        if(val.maps && val.maps.length !== 0){
            for(let i=0;i<val?.maps?.length;i++){
                let item = val?.maps[i]
                await threeClient.setNormalMap(item.url,item.map,val.color,curCode)
            }
        }
        setTabs(cpTabs)
        setLoading(false)
        return true
    }

    //tab切换
    const onTabsChange = async (k, ts = tabs, tc = threeClient) => {
        const val = ts.find(i => i.color === k)
        setLoading(true)
        try {
            for(let i=0;i<maps.length;i++){
                tc.clearNormalMap(maps[i].value,val.color)
            }
            //加载所有贴图
            if(val?.codes_info && val?.codes_info.length !== 0){
                for(let i=0;i<val.codes_info.length;i++){
                    let item = val.codes_info[i]
                    for(let j=0;j<item?.maps?.length;j++){
                        let jitem = item.maps[j]
                        await tc.setNormalMap(jitem.url,jitem.map,item.color,item.code)
                    }
                    
                }
            }
        } catch (error) {
            console.error(error)
            message.error("加载纹理失败")
        }
        setLoading(false)
        setAk(k)
    }
    

    const columns = [
        {
          title: '部位名称',
          dataIndex: 'txt',
          key: 'txt',
          render: (v,r) => (
            <Input placeholder="请输入" allowClear value={v} onChange={e => {
                let cpStateMaterials = cloneDeep(stateMaterials)
                const index = cpStateMaterials.cutparts.findIndex(s => s.code === r.code)
                cpStateMaterials.cutparts[index].txt = e.target.value
                setStateMaterials(cpStateMaterials)
            }} />
          )
        },
        {
            title: '印刷定价',
            dataIndex: 'price',
            key: 'price',
            render: (v,r) => (
                <InputNumber precision={2} value={v} placeholder="请输入" min={0} onChange={e => {
                    let cpStateMaterials = cloneDeep(stateMaterials)
                    const index = cpStateMaterials.cutparts.findIndex(s => s.code === r.code)
                    cpStateMaterials.cutparts[index].price = e
                    setStateMaterials(cpStateMaterials)
                }} />
            )
        },
        {
          title: '裁片图',
          dataIndex: 'img',
          key: 'img',
          render: (v,r) => (
            <Upload value={handleValue(v)} onChange={e => {
                let cpStateMaterials = cloneDeep(stateMaterials)
                const index = cpStateMaterials.cutparts.findIndex(s => s.code === r.code)
                if(e && e.length !== 0){
                    cpStateMaterials.cutparts[index].img = e[0].url
                }else{
                    cpStateMaterials.cutparts[index].img = ""
                }
                setStateMaterials(cpStateMaterials)
            }} />
          )    
        },
        {
          title: '摄像机位置',
          dataIndex: 'camera',
          key: 'camera',
          render: (v,r) => (
            <>
                <Button loading={loading} type="link" style={{padding: 0}} onClick={() => {
                    let cpStateMaterials = cloneDeep(stateMaterials)
                    const index = cpStateMaterials.cutparts.findIndex(s => s.code === r.code)
                    cpStateMaterials.cutparts[index].camera = cloneDeep(threeClient.getCameraPosition())
                    setStateMaterials(cpStateMaterials)
                    message.success("操作成功")
                }}>快照</Button>
                <div></div>
                {
                    v && <Button loading={loading} type="link" style={{padding: 0}} onClick={()=>{
                        threeClient.setCamera(v.x,v.y,v.z)
                    }}>复位</Button>
                }
            </>
          )
        },
        {
            title: '操作',
            dataIndex: 'a',
            key: 'a',
            render: (v,r) => (
                <>
                    <Button loading={loading} style={{padding: 0}} type="link" danger onClick={()=> {
                         Modal.confirm({
                            title: "提示",
                            content: <p>确定删除吗?</p>,
                            onOk: async () => {
                                let cpStateMaterials = cloneDeep(stateMaterials)
                                const index = cpStateMaterials.cutparts.findIndex(i => i.code === r.code)
                                cpStateMaterials.cutparts.splice(index,1)
                                setStateMaterials(cpStateMaterials)
                            }
                        })
                    }}>删除</Button>
                </>
            )
        }
    ];
  


    const fileOnchange = async (e) => {
        if(e.target.files && e.target.files.length !== 0){
            setLoading(true)
            try {
                threeClient?.destroy()
                setTabs([])

                const initStateMaterials = {cutparts: []}
                const file = e.target.files[0]
                const uuid = await http.get(apis.UUID)
                const suffix = file.name.slice(file.name.lastIndexOf('.'));
                const filename = md5(uuid) + suffix;
                const data = await ossClient.put(process.env.REACT_APP_OSS_BUCKET_DIR+"/"+filename, file);
                initStateMaterials.obj_url = data.name
                //启动3D场景
                let ops = {
                    canvasDom: canvasRef?.current,
                    canvasWidth: 375,
                    canvasHeight: 667
                }
                //初始化3DClient
                let client = new Client3D(ops)
                setThreeClient(client)
                //启动3D场景
                client.start()
                const action3D = await client.loadModel(process.env.REACT_APP_OSS_URL+initStateMaterials.obj_url, (p) => {
                    console.log(p)
                })
               // console.log(122222,action3D?.getObjects())
                setMeshs(action3D?.getObjects()?.children)
                setStateMaterials(initStateMaterials)
            } catch (error) {
                console.error(error)
                message.error("上传出现了错误,请检查文件")
            }
            setLoading(false)
            document.getElementById("mconfigFile").value = ""
        }
    }

    const save = async () => {
        let cpStateMaterials = cloneDeep(stateMaterials)
        if(cpStateMaterials.cutparts.length === 0){
            message.error("请添加部位")
            return
        }
        for(let i=0;i<cpStateMaterials.cutparts.length;i++){
            let item = cpStateMaterials.cutparts[i]
            if(!item.txt || !item.txt.trim()){
                message.error("请填写部位名称")
                return
            }
        }
        setLoading(true)
        try {
            const cpTabs = cloneDeep(tabs)
            for(let i=0;i<cpTabs.length;i++){
                delete cpTabs[i].label
            }
            cpStateMaterials.map_info = cpTabs
            try {
                const params = new URLSearchParams(l.search)
                const id = params.get("id")
                await http.post(apis.PRODUCT_MATERIALS_UPDATE, {
                    materials: JSON.stringify(cpStateMaterials),
                    id: parseInt(id)
                })
                message.success("保存成功")
                n("/product/list")
            } catch (error) {
                message.error("保存失败")
            }
        } catch (error) {
            message.info("请检查空缺项")
            console.log(error)
        }
        setLoading(false)
    }

    const headTxt = (v) => {
        let f = stateMaterials?.cutparts?.find(i => i.code === v.name)
        let curTab = tabs?.find(i => i.color == ak)
        let colorInfo = curTab?.codes_info?.find(i => i.code == v.name)
        let sy = {
            width: 100,
            display: "inline-block",
            textOverflow: "ellipsis",
            overflow: "hidden",
            whiteSpace: "nowrap"
        }
        if(f){
            return <div>
                <span style={sy}>{f.txt}</span>
                <span style={{width: 20,height: 20,background: colorInfo?.color,display: "inline-block"}}></span>
            </div>
        }else{
            return <div>
                <span style={sy}>{v.name}</span>
                <span style={{width: 20,height: 20,background: colorInfo?.color,display: "inline-block"}}></span>
            </div>
        }
    }

    const tabsChange = (t = []) => {
        const arr = []
        for(let i=0;i<t.length;i++){
            let item = t[i]
            arr.push({
                label: <TabLabel name={item.name} color={item.color} />,
                key: item.color
            })
        }
        return arr
    }

    return (
        <Spin spinning={loading}>
            <div style={{
                height: "calc(100vh - 235px)",
                overflowX: 'auto',
                overflowY:"hidden",
                position: "relative"
            }}>
                <NormalTexture funcs={normalTextureRef} onChange={normalTextureOnchange} />
                <input id='mconfigFile' accept='.glb,.obj' onChange={fileOnchange} style={{display: "none"}} type="file" />
                <label htmlFor='mconfigFile' style={{
                    width: 180,
                    height: 32,
                    position: "absolute",
                    top: 0,
                    bottom: 0,
                    left: 0,
                    right: 0,
                    margin: "auto",
                    cursor: 'pointer',
                    pointerEvents: loading ? 'none':'auto',
                    display: threeClient ? 'none':'block'
                }}>
                    <Button loading={loading} style={{
                    width: 180,
                    height: 32,
                    pointerEvents: 'none'
                }} type="primary" icon={<FolderOpenOutlined />}>选择.glb或.obj文件</Button></label>

                <div style={{
                    display: threeClient ? "block":"none"
                }}>
                    <div>
                        <Tabs
                            type="editable-card"
                            tabBarStyle={{margin: 0}}
                            onChange={onTabsChange}
                            activeKey={ak}
                            onEdit={onEdit}
                            items={tabsChange(tabs)}
                            tabBarExtraContent={{
                                left: <Button onClick={editMap} disabled={!tabs || tabs?.length === 0} type="link">编辑</Button>
                            }}
                        />
                        <div style={{display: "flex"}}>
                            <div style={{padding: 8}}>
                                <h4>全部部位列表({meshs?.length})</h4>
                                <Collapse
                                    accordion
                                    style={{ background: token.colorBgContainer,width: 200, height: 600, overflow:"auto" }}
                                    onChange={e => {
                                        setCurCode(e)
                                        threeClient.activate(e)
                                    }}
                                >
                                    {
                                        meshs?.map((v) => (
                                            <Panel header={headTxt(v)} key={v.name}>
                                                <Space>
                                                    <Button disabled={tabs?.length == 0} onClick={() => {
                                                        editColorSingle(v)
                                                    }} type="link" style={{padding: 0}}>材质</Button>
                                                    <Button disabled={!!stateMaterials?.cutparts?.find(i => i.code === curCode)} onClick={confirmPrice} type="link" style={{padding: 0}}>定价</Button>
                                                </Space>
                                            </Panel>
                                        ))
                                    }
                                </Collapse>
                            </div>
                            <div style={{width: 12}}></div>
                            <div style={{
                                width: 375,
                                height: 667, 
                                background: "linear-gradient(180deg, rgba(238,238,238,0) 0%, #F8F8F8 100%)",
                                border: "solid 1px #f5f5f5",
                                borderTop: "none",
                                cursor: "pointer",
                                position: "relative"
                            }}>
                                <canvas style={{display: "block",touchAction: "none"}} ref={canvasRef}></canvas>
                            </div>
                            <div style={{width: 12}}></div>
                            <div style={{padding: 8, minWidth: 600,overflow:"auto"}}>
                                <h4>印刷部位列表({stateMaterials?.cutparts?.length})</h4>
                                <Table scroll={{y: 667 - 55 - 63}} pagination={false} rowKey={"code"} dataSource={stateMaterials?.cutparts} columns={columns} />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div style={{textAlign: "center", marginTop: 12 ,display: threeClient ? "block":"none"}}>
                    <Space>
                        <label htmlFor='mconfigFile' style={{
                            width: 116,
                            height: 32,
                            cursor: 'pointer'
                        }}>
                            <Button loading={loading} style={{
                                width: 116,
                                height: 32,
                                pointerEvents: 'none'
                            }} type="dashed" icon={<FolderOpenOutlined />}>重新选择</Button>
                        </label>
                        <Button type="primary" onClick={save}>保存配置</Button>
                    </Space>
                </div>
        </Spin>
    )
}

export default Index